﻿using System.Xml;

namespace WoWArmoryParser
{
    public class ArmoryParser
    {
        public static Character GetCharacter(string Realm, string Name, RegionEnum Region)
        {
            Character ch = new Character();

            string path = null;
            XmlTextReader doc = default(XmlTextReader);

            try
            {
                path = GetRegionPath(Region) + "/character-sheet.xml";
                doc = GetStream(path, Realm, Name);

                ch.Region = Region;
                ch.IsValid = false;
                while (doc.Read)
                {
                    if (doc.NodeType == XmlNodeType.Element)
                    {
                        if (doc.LocalName == "character")
                        {
                            if (doc.MoveToAttribute("name") && doc.ReadContentAsString().ToLower == Name.ToLower)
                            {
                                ch.Name = doc.GetAttribute("name");
                                if (doc.MoveToAttribute("realm")) ch.Realm = doc.ReadContentAsString;
                                if (doc.MoveToAttribute("class")) ch.CharClass = GetClassEnumFromString(doc.ReadContentAsString);
                                if (doc.MoveToAttribute("gender")) ch.Gender = GetGenderEnumFromString(doc.ReadContentAsString);
                                if (doc.MoveToAttribute("guildName")) ch.GuildName = doc.ReadContentAsString;
                                if (doc.MoveToAttribute("level")) ch.Level = doc.ReadContentAsInt;
                                if (doc.MoveToAttribute("race")) ch.Race = GetRaceEnumFromString(doc.ReadContentAsString);
                                if (doc.MoveToAttribute("lastModified")) ch.LastUpdate = DateTime.Parse(doc.ReadContentAsString);
                                if (doc.MoveToAttribute("factionId")) ch.Faction = doc.ReadContentAsInt;
                            }
                        }

                        if (doc.LocalName == "characterTab") ch.IsValid = true;

                        if (doc.LocalName == "lifetimehonorablekills")
                        {
                            if (doc.MoveToAttribute("value")) ch.LifeTimeHonorableKills = doc.ReadContentAsInt;
                        }


                        if (doc.LocalName == "arenaTeam")
                        {
                            switch (doc.GetAttribute("size"))
                            {
                                case "2":
                                    ch.Team2v2Name = doc.GetAttribute("name");
                                    break;
                                case "3":
                                    ch.Team3v3Name = doc.GetAttribute("name");
                                    break;
                                case "5":
                                    ch.Team5v5Name = doc.GetAttribute("name");
                                    break;
                            }
                        }


                        if (doc.LocalName == "talentSpec")
                        {
                            int t1 = 0;
                            int t2 = 0;
                            int t3 = 0;
                            if (doc.MoveToAttribute("treeOne")) t1 = doc.ReadContentAsInt;
                            if (doc.MoveToAttribute("treeTwo")) t2 = doc.ReadContentAsInt;
                            if (doc.MoveToAttribute("treeThree")) t3 = doc.ReadContentAsInt;
                            ch.TalentSpec = new TalentSpec(t1, t2, t3);
                        }


                        if (doc.LocalName == "health")
                        {
                            CharacterBar cb = new CharacterBar();
                            cb.Type = BarType.Health;
                            if (doc.MoveToAttribute("effective")) cb.Total = doc.ReadContentAsInt;
                            ch.HealthBar = cb;
                        }
                        if (doc.LocalName == "secondBar")
                        {
                            CharacterBar cb = new CharacterBar();
                            if (doc.MoveToAttribute("effective")) cb.Total = doc.ReadContentAsInt;
                            string type = "";
                            if (doc.MoveToAttribute("type")) type = doc.ReadContentAsString;
                            switch (type)
                            {
                                case "m":
                                    cb.Type = BarType.Mana;
                                    break;
                                case "e":
                                    cb.Type = BarType.Energy;
                                    break;
                                case "r":
                                    cb.Type = BarType.Rage;
                                    break;
                                default:
                                    throw new SecondBarTypeNotValidException();
                            }
                            ch.SecondBar = cb;
                        }

                        if (doc.LocalName == "baseStats")
                        {
                            using (XmlReader stat = doc.ReadSubtree)
                            {
                                while (stat.Read)
                                {
                                    if (stat.LocalName == "strength" && stat.MoveToAttribute("effective")) ch.BaseStats.Strength = stat.ReadContentAsInt;
                                    if (stat.LocalName == "agility" && stat.MoveToAttribute("effective")) ch.BaseStats.Agility = stat.ReadContentAsInt;
                                    if (stat.LocalName == "stamina" && stat.MoveToAttribute("effective")) ch.BaseStats.Stamina = stat.ReadContentAsInt;
                                    if (stat.LocalName == "intellect" && stat.MoveToAttribute("effective")) ch.BaseStats.Intellect = stat.ReadContentAsInt;
                                    if (stat.LocalName == "spirit" && stat.MoveToAttribute("effective")) ch.BaseStats.Spirit = stat.ReadContentAsInt;
                                    if (stat.LocalName == "armor" && stat.MoveToAttribute("effective")) ch.BaseStats.Armor = stat.ReadContentAsInt;
                                }
                                stat.Close();
                            }
                        }


                        if (doc.LocalName == "resistances")
                        {
                            using (XmlReader res = doc.ReadSubtree)
                            {
                                while (res.Read)
                                {
                                    if (res.LocalName == "arcane" && res.MoveToAttribute("value")) ch.Resistances.ArcaneRes = res.ReadContentAsInt;
                                    if (res.LocalName == "fire" && res.MoveToAttribute("value")) ch.Resistances.FireRes = res.ReadContentAsInt;
                                    if (res.LocalName == "frost" && res.MoveToAttribute("value")) ch.Resistances.FrostRes = res.ReadContentAsInt;
                                    if (res.LocalName == "holy" && res.MoveToAttribute("value")) ch.Resistances.HolyRes = res.ReadContentAsInt;
                                    if (res.LocalName == "nature" && res.MoveToAttribute("value")) ch.Resistances.NatureRes = res.ReadContentAsInt;
                                    if (res.LocalName == "shadow" && res.MoveToAttribute("value")) ch.Resistances.ShadowRes = res.ReadContentAsInt;
                                }
                                res.Close();
                            }
                        }

                        if (doc.LocalName == "spell")
                        {
                            using (XmlReader spell = doc.ReadSubtree)
                            {
                                while (spell.Read)
                                {
                                    if (spell.LocalName == "bonusDamage")
                                    {
                                        using (XmlReader dmg = spell.ReadSubtree)
                                        {
                                            while (dmg.Read)
                                            {
                                                if (dmg.LocalName == "arcane" && dmg.MoveToAttribute("value")) ch.Spell.Arcane.DamageBonus = dmg.ReadContentAsInt;
                                                if (dmg.LocalName == "fire" && dmg.MoveToAttribute("value")) ch.Spell.Fire.DamageBonus = dmg.ReadContentAsInt;
                                                if (dmg.LocalName == "frost" && dmg.MoveToAttribute("value")) ch.Spell.Frost.DamageBonus = dmg.ReadContentAsInt;
                                                if (dmg.LocalName == "holy" && dmg.MoveToAttribute("value")) ch.Spell.Holy.DamageBonus = dmg.ReadContentAsInt;
                                                if (dmg.LocalName == "nature" && dmg.MoveToAttribute("value")) ch.Spell.Nature.DamageBonus = dmg.ReadContentAsInt;
                                                if (dmg.LocalName == "shadow" && dmg.MoveToAttribute("value")) ch.Spell.Shadow.DamageBonus = dmg.ReadContentAsInt;
                                            }
                                            dmg.Close();
                                        }
                                    }
                                    else if (spell.LocalName == "critChance")
                                    {

                                        using (XmlReader crit = spell.ReadSubtree)
                                        {
                                            while (crit.Read)
                                            {
                                                if (crit.LocalName == "arcane" && crit.MoveToAttribute("percent"))
                                                {
                                                    ch.Spell.Arcane.CritChance = crit.ReadContentAsDouble;
                                                }
                                                else if (crit.LocalName == "fire" && crit.MoveToAttribute("percent"))
                                                {
                                                    ch.Spell.Fire.CritChance = crit.ReadContentAsDouble;
                                                }
                                                else if (crit.LocalName == "frost" && crit.MoveToAttribute("percent"))
                                                {
                                                    ch.Spell.Frost.CritChance = crit.ReadContentAsDouble;
                                                }
                                                else if (crit.LocalName == "holy" && crit.MoveToAttribute("percent"))
                                                {
                                                    ch.Spell.Holy.CritChance = crit.ReadContentAsDouble;
                                                }
                                                else if (crit.LocalName == "nature" && crit.MoveToAttribute("percent"))
                                                {
                                                    ch.Spell.Nature.CritChance = crit.ReadContentAsDouble;
                                                }
                                                else if (crit.LocalName == "shadow" && crit.MoveToAttribute("percent"))
                                                {
                                                    ch.Spell.Shadow.CritChance = crit.ReadContentAsDouble;
                                                }
                                            }
                                            crit.Close();
                                        }
                                        if (spell.MoveToAttribute("rating")) ch.Spell.CritRating = spell.ReadContentAsInt;
                                    }
                                    else if (spell.LocalName == "hitRating")
                                    {
                                        if (spell.MoveToAttribute("increasedHitPercent")) ch.Spell.HitRating.IncreasedHitChance = spell.ReadContentAsDouble;
                                        if (spell.MoveToAttribute("value")) ch.Spell.HitRating.Value = spell.ReadContentAsInt;
                                    }
                                    else if (spell.LocalName == "bonusHealing" && spell.MoveToAttribute("value"))
                                    {
                                        ch.Spell.HealingBonus = spell.ReadContentAsInt;
                                    }
                                    else if (spell.LocalName == "penetration" && spell.MoveToAttribute("value"))
                                    {
                                        ch.Spell.SpellPenetration = spell.ReadContentAsInt;
                                    }
                                    else if (spell.LocalName == "manaRegen")
                                    {
                                        if (spell.MoveToAttribute("casting")) ch.Spell.ManaRegen.WhileCasting = spell.ReadContentAsDouble;
                                        if (spell.MoveToAttribute("notCasting")) ch.Spell.ManaRegen.WhileNotCasting = spell.ReadContentAsDouble;
                                    }
                                }
                                spell.Close();
                            }
                        }

                        if (doc.LocalName == "melee")
                        {
                            using (XmlReader melee = doc.ReadSubtree)
                            {
                                while (melee.Read)
                                {
                                    if (melee.LocalName == "mainHandWeaponSkill")
                                    {
                                        if (melee.MoveToAttribute("rating")) ch.Melee.MainHand.Skill.Rating = melee.ReadContentAsInt;
                                        if (melee.MoveToAttribute("value")) ch.Melee.MainHand.Skill.Value = melee.ReadContentAsInt;
                                    }
                                    if (melee.LocalName == "mainHandDamage")
                                    {
                                        if (melee.MoveToAttribute("dps")) ch.Melee.MainHand.Damage.DPS = melee.ReadContentAsDouble;
                                        if (melee.MoveToAttribute("max")) ch.Melee.MainHand.Damage.Max = melee.ReadContentAsInt;
                                        if (melee.MoveToAttribute("min")) ch.Melee.MainHand.Damage.Min = melee.ReadContentAsInt;
                                        if (melee.MoveToAttribute("percent")) ch.Melee.MainHand.Damage.Percent = melee.ReadContentAsDouble;
                                        if (melee.MoveToAttribute("speed")) ch.Melee.MainHand.Damage.Speed = melee.ReadContentAsDouble;
                                    }
                                    if (melee.LocalName == "mainHandSpeed")
                                    {
                                        if (melee.MoveToAttribute("hastePercent")) ch.Melee.MainHand.Speed.HastePercent = melee.ReadContentAsDouble;
                                        if (melee.MoveToAttribute("hasteRating")) ch.Melee.MainHand.Speed.HasteRating = melee.ReadContentAsInt;
                                        if (melee.MoveToAttribute("value")) ch.Melee.MainHand.Speed.Value = melee.ReadContentAsDouble;
                                    }
                                    if (melee.LocalName == "offHandWeaponSkill")
                                    {
                                        if (melee.MoveToAttribute("rating")) ch.Melee.OffHand.Skill.Rating = melee.ReadContentAsInt;
                                        if (melee.MoveToAttribute("value")) ch.Melee.OffHand.Skill.Value = melee.ReadContentAsInt;
                                    }
                                    if (melee.LocalName == "offHandDamage")
                                    {
                                        if (melee.MoveToAttribute("dps")) ch.Melee.OffHand.Damage.DPS = melee.ReadContentAsDouble;
                                        if (melee.MoveToAttribute("max")) ch.Melee.OffHand.Damage.Max = melee.ReadContentAsInt;
                                        if (melee.MoveToAttribute("min")) ch.Melee.OffHand.Damage.Min = melee.ReadContentAsInt;
                                        if (melee.MoveToAttribute("percent")) ch.Melee.OffHand.Damage.Percent = melee.ReadContentAsDouble;
                                        if (melee.MoveToAttribute("speed")) ch.Melee.OffHand.Damage.Speed = melee.ReadContentAsDouble;
                                    }
                                    if (melee.LocalName == "offHandSpeed")
                                    {
                                        if (melee.MoveToAttribute("hastePercent")) ch.Melee.OffHand.Speed.HastePercent = melee.ReadContentAsDouble;
                                        if (melee.MoveToAttribute("hasteRating")) ch.Melee.OffHand.Speed.HasteRating = melee.ReadContentAsInt;
                                        if (melee.MoveToAttribute("value")) ch.Melee.OffHand.Speed.Value = melee.ReadContentAsDouble;
                                    }
                                    if (melee.LocalName == "hitRating")
                                    {
                                        if (melee.MoveToAttribute("increasedHitPercent")) ch.Melee.HitRating.IncreasedHitChance = melee.ReadContentAsDouble;
                                        if (melee.MoveToAttribute("value")) ch.Melee.HitRating.Value = melee.ReadContentAsInt;
                                    }
                                    if (melee.LocalName == "power")
                                    {
                                        if (melee.MoveToAttribute("base")) ch.Melee.AttackPower.Base = melee.ReadContentAsInt;
                                        if (melee.MoveToAttribute("effective")) ch.Melee.AttackPower.Effective = melee.ReadContentAsInt;
                                        if (melee.MoveToAttribute("increasedDps")) ch.Melee.AttackPower.IncreasedDPS = melee.ReadContentAsDouble;
                                    }
                                    if (melee.LocalName == "critChance")
                                    {
                                        if (melee.MoveToAttribute("percent")) ch.Melee.CritChance.Percent = melee.ReadContentAsDouble;
                                        if (melee.MoveToAttribute("plusPercent")) ch.Melee.CritChance.IncreasedByRating = melee.ReadContentAsDouble;
                                        if (melee.MoveToAttribute("rating")) ch.Melee.CritChance.Rating = melee.ReadContentAsInt;
                                    }
                                }
                                melee.Close();
                            }
                        }

                        if (doc.LocalName == "ranged")
                        {
                            using (XmlReader ranged = doc.ReadSubtree)
                            {
                                while (ranged.Read)
                                {
                                    if (ranged.LocalName == "weaponSkill")
                                    {
                                        if (ranged.MoveToAttribute("rating")) ch.Ranged.Weapon.Skill.Rating = ranged.ReadContentAsInt;
                                        if (ranged.MoveToAttribute("value")) ch.Ranged.Weapon.Skill.Value = ranged.ReadContentAsInt;
                                    }
                                    if (ranged.LocalName == "damage")
                                    {
                                        if (ranged.MoveToAttribute("dps")) ch.Ranged.Weapon.Damage.DPS = ranged.ReadContentAsDouble;
                                        if (ranged.MoveToAttribute("max")) ch.Ranged.Weapon.Damage.Max = ranged.ReadContentAsInt;
                                        if (ranged.MoveToAttribute("min")) ch.Ranged.Weapon.Damage.Min = ranged.ReadContentAsInt;
                                        if (ranged.MoveToAttribute("percent")) ch.Ranged.Weapon.Damage.Percent = ranged.ReadContentAsDouble;
                                        if (ranged.MoveToAttribute("speed")) ch.Ranged.Weapon.Damage.Speed = ranged.ReadContentAsDouble;
                                    }
                                    if (ranged.LocalName == "speed")
                                    {
                                        if (ranged.MoveToAttribute("hastePercent")) ch.Ranged.Weapon.Speed.HastePercent = ranged.ReadContentAsDouble;
                                        if (ranged.MoveToAttribute("hasteRating")) ch.Ranged.Weapon.Speed.HasteRating = ranged.ReadContentAsInt;
                                        if (ranged.MoveToAttribute("value")) ch.Ranged.Weapon.Speed.Value = ranged.ReadContentAsDouble;
                                    }
                                    if (ranged.LocalName == "hitRating")
                                    {
                                        if (ranged.MoveToAttribute("increasedHitPercent")) ch.Ranged.HitRating.IncreasedHitChance = ranged.ReadContentAsDouble;
                                        if (ranged.MoveToAttribute("value")) ch.Ranged.HitRating.Value = ranged.ReadContentAsInt;
                                    }
                                    if (ranged.LocalName == "power")
                                    {
                                        if (ranged.MoveToAttribute("base")) ch.Ranged.AttackPower.Base = ranged.ReadContentAsInt;
                                        if (ranged.MoveToAttribute("effective")) ch.Ranged.AttackPower.Effective = ranged.ReadContentAsInt;
                                        if (ranged.MoveToAttribute("increasedDps")) ch.Ranged.AttackPower.IncreasedDPS = ranged.ReadContentAsDouble;
                                    }
                                    if (ranged.LocalName == "critChance")
                                    {
                                        if (ranged.MoveToAttribute("percent")) ch.Ranged.CritChance.Percent = ranged.ReadContentAsDouble;
                                        if (ranged.MoveToAttribute("plusPercent")) ch.Ranged.CritChance.IncreasedByRating = ranged.ReadContentAsDouble;
                                        if (ranged.MoveToAttribute("rating")) ch.Ranged.CritChance.Rating = ranged.ReadContentAsInt;
                                    }
                                }
                                ranged.Close();
                            }
                        }

                        if (doc.LocalName == "defenses")
                        {
                            using (XmlReader def = doc.ReadSubtree)
                            {
                                DefenseInfo defense = ch.Defense;
                                while (def.Read)
                                {
                                    if (def.LocalName == "armor")
                                    {
                                        if (def.MoveToAttribute("base")) defense.Armor.Base = def.ReadContentAsInt;
                                        if (def.MoveToAttribute("effective")) defense.Armor.Effective = def.ReadContentAsInt;
                                        if (def.MoveToAttribute("percent")) defense.Armor.DamageReductionPercent = def.ReadContentAsDouble;
                                    }
                                    if (def.LocalName == "defense")
                                    {
                                        if (def.MoveToAttribute("rating")) defense.Defense.Rating = def.ReadContentAsDouble;
                                        if (def.MoveToAttribute("value")) defense.Defense.Value = def.ReadContentAsDouble;
                                    }
                                    if (def.LocalName == "dodge")
                                    {
                                        if (def.MoveToAttribute("increasePercent")) defense.Dodge.IncreasedByRating = def.ReadContentAsDouble;
                                        if (def.MoveToAttribute("percent")) defense.Dodge.Percent = def.ReadContentAsDouble;
                                        if (def.MoveToAttribute("rating")) defense.Dodge.Rating = def.ReadContentAsDouble;
                                    }
                                    if (def.LocalName == "parry")
                                    {
                                        if (def.MoveToAttribute("increasePercent")) defense.Parry.IncreasedByRating = def.ReadContentAsDouble;
                                        if (def.MoveToAttribute("percent")) defense.Parry.Percent = def.ReadContentAsDouble;
                                        if (def.MoveToAttribute("rating")) defense.Parry.Rating = def.ReadContentAsDouble;
                                    }
                                    if (def.LocalName == "block")
                                    {
                                        if (def.MoveToAttribute("increasePercent")) defense.Block.IncreasedByRating = def.ReadContentAsDouble;
                                        if (def.MoveToAttribute("percent")) defense.Block.Percent = def.ReadContentAsDouble;
                                        if (def.MoveToAttribute("rating")) defense.Block.Rating = def.ReadContentAsDouble;
                                    }
                                    if (def.LocalName == "resilience")
                                    {
                                        if (def.MoveToAttribute("damagePercent")) defense.Resilience.DamageReduction = def.ReadContentAsDouble;
                                        if (def.MoveToAttribute("hitPercent")) defense.Resilience.HitReduction = def.ReadContentAsDouble;
                                        if (def.MoveToAttribute("value")) defense.Resilience.Rating = def.ReadContentAsDouble;
                                    }
                                }
                                def.Close();
                            }
                        }

                        if (doc.LocalName == "items")
                        {
                            using (XmlReader itm = doc.ReadSubtree)
                            {
                                while (itm.Read)
                                {
                                    if (itm.LocalName == "item")
                                    {
                                        EquipSlotEnum slot = default(EquipSlotEnum);
                                        int id = 0;

                                        if (itm.MoveToAttribute("slot")) slot = itm.ReadContentAsInt;
                                        if (itm.MoveToAttribute("id")) id = itm.ReadContentAsInt;

                                        ch.Equip.ItemID(slot) = id;
                                    }
                                }
                                itm.Close();
                            }
                        }
                    }
                }
                doc.Close();



                path = GetRegionPath(Region) + "/character-skills.xml";
                doc = GetStream(path, Realm, Name);

                while (doc.Read)
                {
                    if (doc.NodeType == XmlNodeType.Element)
                    {

                        if (doc.LocalName == "skillCategory" && doc.GetAttribute("key") == "professions") ch.Skills.Professions = GetSkillList(doc);
                        if (doc.LocalName == "skillCategory" && doc.GetAttribute("key") == "secondaryskills") ch.Skills.SecondarySkills = GetSkillList(doc);
                        if (doc.LocalName == "skillCategory" && doc.GetAttribute("key") == "weaponskills") ch.Skills.WeaponsSkills = GetSkillList(doc);
                        if (doc.LocalName == "skillCategory" && doc.GetAttribute("key") == "classskills") ch.Skills.ClassSkills = GetSkillList(doc);
                        if (doc.LocalName == "skillCategory" && doc.GetAttribute("key") == "armorproficiencies") ch.Skills.ArmorProficiencies = GetSkillList(doc);
                        if (doc.LocalName == "skillCategory" && doc.GetAttribute("key") == "languages") ch.Skills.Languages = GetSkillList(doc);
                    }
                }
                doc.Close();


                path = GetRegionPath(Region) + "/character-reputation.xml";
                doc = GetStream(path, Realm, Name);

                while (doc.Read)
                {
                    if (doc.NodeType == XmlNodeType.Element)
                    {

                        if (doc.LocalName == "factionCategory" && (doc.GetAttribute("key") == "horde" || doc.GetAttribute("key") == "alliance")) ch.GroupedReputations.Faction = GetRepsList(ch, doc.GetAttribute("name"), doc);
                        if (doc.LocalName == "factionCategory" && (doc.GetAttribute("key") == "hordeforces" || doc.GetAttribute("key") == "allianceforces")) ch.GroupedReputations.BattleGrounds = GetRepsList(ch, doc.GetAttribute("name"), doc);
                        if (doc.LocalName == "factionCategory" && doc.GetAttribute("key") == "outland") ch.GroupedReputations.Outland = GetRepsList(ch, doc.GetAttribute("name"), doc);
                        if (doc.LocalName == "factionCategory" && doc.GetAttribute("key") == "shattrathcity") ch.GroupedReputations.ShattrathCity = GetRepsList(ch, doc.GetAttribute("name"), doc);
                        if (doc.LocalName == "factionCategory" && doc.GetAttribute("key") == "steamwheedlecartel") ch.GroupedReputations.SteamwheedleCartel = GetRepsList(ch, doc.GetAttribute("name"), doc);
                        if (doc.LocalName == "factionCategory" && doc.GetAttribute("key") == "zother") ch.GroupedReputations.Others = GetRepsList(ch, doc.GetAttribute("name"), doc);
                    }
                }
                doc.Close();
            }
            catch (Exception ex)
            {
                ch.IsValid = false;
            }
            return ch;
        }

        public static Guild GetGuild(string Realm, string Name, RegionEnum Region)
        {
            Guild g = new Guild();
            string path = GetRegionPath(Region) + "/guild-info.xml";
            using (XmlReader doc = GetStream(path, Realm, Name))
            {

                g.Region = Region;
                while (doc.Read)
                {
                    if (doc.NodeType == XmlNodeType.Element)
                    {
                        if (doc.LocalName == "guild")
                        {
                            g.BattleGroup = doc.GetAttribute("battleGroup");
                            g.Realm = doc.GetAttribute("realm");
                            g.Name = doc.GetAttribute("name");
                        }
                        if (doc.LocalName == "character")
                        {
                            GuildMember member = new GuildMember(doc.GetAttribute("name"), g.Realm, Region);
                            {
                                member.CharClass = GetClassEnumFromString(doc.GetAttribute("class"));
                                member.Gender = GetGenderEnumFromString(doc.GetAttribute("gender"));
                                member.Race = GetRaceEnumFromString(doc.GetAttribute("race"));
                                member.Level = doc.GetAttribute("level");
                                member.Rank = doc.GetAttribute("rank");
                            }
                            if (doc.GetAttribute("rank") == 0) g.GuildMaster = member;
                            g.Members.Add(member);
                        }
                    }

                }
            }
            return g;
        }

        public static ArenaTeam GetArenaTeam(string Realm, string Name, ArenaTeamSizeEnum Size, RegionEnum Region)
        {
            ArenaTeam at = new ArenaTeam();
            string path = GetRegionPath(Region) + "/team-info.xml";
            using (XmlReader doc = GetStream(path, Realm, Name, Size))
            {

                at.Region = Region;
                while (doc.Read)
                {
                    if (doc.NodeType == XmlNodeType.Element)
                    {
                        if (doc.LocalName == "arenaTeam")
                        {
                            at.BattleGroup = doc.GetAttribute("battleGroup");
                            at.Faction = (int)doc.GetAttribute("factionID");
                            at.Name = doc.GetAttribute("name");
                            at.Ranking = doc.GetAttribute("ranking");
                            at.Rating = doc.GetAttribute("rating");
                            at.Size = (int)doc.GetAttribute("size");
                            at.Realm = doc.GetAttribute("realm");
                            {
                                at.GamesInWeek.Played = doc.GetAttribute("gamesPlayed");
                                at.GamesInWeek.Wins = doc.GetAttribute("gamesWon");
                            }
                            {
                                at.GamesInSeason.Played = doc.GetAttribute("seasonGamesPlayed");
                                at.GamesInSeason.Wins = doc.GetAttribute("seasonGamesWon");
                            }
                        }
                        else if (doc.LocalName == "emblem")
                        {
                            {
                                at.Emblem.BackgroundColor = doc.GetAttribute("background");
                                at.Emblem.BorderColor = doc.GetAttribute("borderColor");
                                at.Emblem.IconColor = doc.GetAttribute("iconColor");
                                at.Emblem.BorderStyle = doc.GetAttribute("borderStyle");
                                at.Emblem.IconStyle = doc.GetAttribute("iconStyle");
                            }
                        }
                        else if (doc.LocalName == "character")
                        {
                            ArenaMember member = new ArenaMember(doc.GetAttribute("name"), Realm, Region);
                            {
                                member.CharClass = GetClassEnumFromString(doc.GetAttribute("class"));
                                member.Gender = GetGenderEnumFromString(doc.GetAttribute("gender"));
                                member.Race = GetRaceEnumFromString(doc.GetAttribute("race"));
                                member.Rank = doc.GetAttribute("teamRank");
                                member.GuildName = doc.GetAttribute("guild");
                                {
                                    member.GamesInWeek.Played = doc.GetAttribute("gamesPlayed");
                                    member.GamesInWeek.Wins = doc.GetAttribute("gamesWon");
                                }
                                {
                                    member.GamesInSeason.Played = doc.GetAttribute("seasonGamesPlayed");
                                    member.GamesInSeason.Wins = doc.GetAttribute("seasonGamesWon");
                                }
                            }
                            if (doc.GetAttribute("teamRank") == 0) at.Leader = member;
                            at.Members.Add(member);
                        }
                    }
                }
            }
            return at;
        }

        public static Item GetItem(int ID)
        {
            Item i = new Item();
            string path = GetRegionPath(RegionEnum.USA) + "/item-info.xml";

            using (XmlReader doc = GetStream(path, ID))
            {
                while (doc.Read)
                {
                    if (doc.NodeType == XmlNodeType.Element)
                    {
                        if (doc.LocalName == "item")
                        {
                            if (doc.MoveToAttribute("id") && doc.ReadContentAsInt == ID)
                            {
                                i.ID = ID;
                                if (doc.MoveToAttribute("icon")) i.Icon = doc.ReadContentAsString;
                                if (doc.MoveToAttribute("level")) i.Level = doc.ReadContentAsInt;
                                if (doc.MoveToAttribute("name")) i.Name = doc.ReadContentAsString;
                                if (doc.MoveToAttribute("quality")) i.Quality = doc.ReadContentAsInt;
                                i.IsValid = true;
                            }
                        }
                    }
                }
                doc.Close();
            }
            return i;
        }

        protected static internal string GetRegionPath(RegionEnum Region)
        {
            string path = "";
            switch (Region)
            {
                case RegionEnum.Europe:
                    path = "http://eu.wowarmory.com";
                    break;
                case RegionEnum.USA:
                    path = "http://www.wowarmory.com";
                    break;
            }
            return path;
        }

        protected static Xml.XmlTextReader GetStream(string Path, string Realm, string Name)
        {
            Net.WebClient wc = new Net.WebClient();
            Xml.XmlTextReader xtr = default(Xml.XmlTextReader);
            wc.QueryString.Add("r", Realm);
            wc.QueryString.Add("n", Name);
            wc.Headers.Add("user-agent", "MSIE 7.0");
            xtr = new Xml.XmlTextReader(wc.OpenRead(Path));
            return xtr;
        }

        protected static XmlTextReader GetStream(string Path, int ItemID)
        {
            Net.WebClient wc = new Net.WebClient();
            Xml.XmlTextReader xtr = default(Xml.XmlTextReader);
            wc.QueryString.Add("i", ItemID);
            wc.Headers.Add("user-agent", "MSIE 7.0");
            xtr = new Xml.XmlTextReader(wc.OpenRead(Path));
            return xtr;
        }

        protected static Xml.XmlTextReader GetStream(string Path, string Realm, string Name, ArenaTeamSizeEnum Size)
        {
            Net.WebClient wc = new Net.WebClient();
            Xml.XmlTextReader xtr = default(Xml.XmlTextReader);
            wc.QueryString.Add("r", Realm);
            wc.QueryString.Add("t", Name);
            wc.QueryString.Add("ts", (int)Size);
            wc.Headers.Add("user-agent", "MSIE 7.0");
            xtr = new Xml.XmlTextReader(wc.OpenRead(Path));
            return xtr;
        }

        protected static GroupedReputationCollection GetRepsList(ref Character ch, string FactionCategory, XmlTextReader xml)
        {
            GroupedReputationCollection list = new GroupedReputationCollection(FactionCategory);
            if (xml.NodeType == XmlNodeType.Element)
            {
                using (XmlReader reps = xml.ReadSubtree)
                {
                    while (reps.Read)
                    {
                        if (reps.NodeType == XmlNodeType.Element && reps.LocalName == "faction")
                        {
                            Reputation re = new Reputation();
                            {
                                re.Key = reps.GetAttribute("key");
                                re.Name = reps.GetAttribute("name");
                                re.Value = reps.GetAttribute("reputation");
                            }
                            list.Add(re.Key, re);
                            ch.Reputations.Add(re.Key, re);
                        }
                    }
                }
            }
            return list;
        }

        protected static SkillCollection GetSkillList(ref XmlTextReader xml)
        {
            SkillCollection list = new SkillCollection();
            using (XmlReader skillz = xml.ReadSubtree)
            {
                while (skillz.Read)
                {
                    if (skillz.NodeType == XmlNodeType.Element && !(skillz.LocalName == "skillCategory"))
                    {
                        Skill sk = new Skill();
                        {
                            sk.Key = skillz.GetAttribute("key");
                            sk.Max = skillz.GetAttribute("max");
                            sk.Name = skillz.GetAttribute("name");
                            sk.Value = skillz.GetAttribute("value");
                        }
                        list.Add(sk);
                    }
                }
                skillz.Close();
            }
            return list;
        }

        protected static ClassEnum GetClassEnumFromString(string Cls)
        {
            ClassEnum res = default(ClassEnum);
            switch (Cls.ToLower)
            {
                case "druid":
                    res = ClassEnum.Druid;
                    break;
                case "hunter":
                    res = ClassEnum.Hunter;
                    break;
                case "mage":
                    res = ClassEnum.Mage;
                    break;
                case "paladin":
                    res = ClassEnum.Paladin;
                    break;
                case "priest":
                    res = ClassEnum.Priest;
                    break;
                case "rogue":
                    res = ClassEnum.Rogue;
                    break;
                case "shaman":
                    res = ClassEnum.Shaman;
                    break;
                case "warlock":
                    res = ClassEnum.Warlock;
                    break;
                case "warrior":
                    res = ClassEnum.Warrior;
                    break;
                default:
                    throw new ClassNotValidException();
            }
            return res;
        }

        protected static GenderEnum GetGenderEnumFromString(string Gender)
        {
            GenderEnum res = default(GenderEnum);
            switch (Gender.ToLower)
            {
                case "male":
                    res = GenderEnum.Male;
                    break;
                case "female":
                    res = GenderEnum.Female;
                    break;
                default:
                    throw new GenderNotValidException();
            }
            return res;
        }

        protected static RaceEnum GetRaceEnumFromString(string Race)
        {
            RaceEnum res = default(RaceEnum);
            switch (Race.ToLower)
            {
                case "blood elf":
                    res = RaceEnum.BloodElf;
                    break;
                case "draenei":
                    res = RaceEnum.Draenei;
                    break;
                case "dwarf":
                    res = RaceEnum.Dwarf;
                    break;
                case "gnome":
                    res = RaceEnum.Gnome;
                    break;
                case "human":
                    res = RaceEnum.Human;
                    break;
                case "night elf":
                    res = RaceEnum.NightElf;
                    break;
                case "orc":
                    res = RaceEnum.Orc;
                    break;
                case "tauren":
                    res = RaceEnum.Tauren;
                    break;
                case "troll":
                    res = RaceEnum.Troll;
                    break;
                case "undead":
                    res = RaceEnum.Undead;
                    break;
                default:
                    throw new RaceNotValidException();
            }
            return res;
        }

        protected RegionEnum _Region;
    }
}
